package com.ck.serviceImpl;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;

import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.ck.dao.ChapterDAO;
import com.ck.dao.PanduanDAO;
import com.ck.dao.SubjectDAO;
import com.ck.dao.TiankongDAO;
import com.ck.dao.XuanzeDAO;
import com.ck.dao.ZhuguanDAO;
import com.ck.domain.Chapter;
import com.ck.domain.Panduan;
import com.ck.domain.Subject;
import com.ck.domain.Tiankong;
import com.ck.domain.Xuanze;
import com.ck.domain.Zhuguan;
import com.ck.service.QuestionService;

public class QuestionServiceImpl implements QuestionService {
	
	private SubjectDAO subjectDAO;
	private ChapterDAO chapterDAO;
	private PanduanDAO panduanDAO;
	private XuanzeDAO xuanzeDAO;
	private TiankongDAO tiankongDAO;
	private ZhuguanDAO zhuguanDAO;
	
	private String rootImageDir;

	public void setSubjectDAO(SubjectDAO subjectDAO) {
		this.subjectDAO = subjectDAO;
	}

	public void setChapterDAO(ChapterDAO chapterDAO) {
		this.chapterDAO = chapterDAO;
	}

	public void setPanduanDAO(PanduanDAO panduanDAO) {
		this.panduanDAO = panduanDAO;
	}

	public void setXuanzeDAO(XuanzeDAO xuanzeDAO) {
		this.xuanzeDAO = xuanzeDAO;
	}

	public void setTiankongDAO(TiankongDAO tiankongDAO) {
		this.tiankongDAO = tiankongDAO;
	}

	public void setZhuguanDAO(ZhuguanDAO zhuguanDAO) {
		this.zhuguanDAO = zhuguanDAO;
	}

	public void setRootImageDir(String rootImageDir) {
		this.rootImageDir = rootImageDir;
	}

	public List<Subject> gainSubjectList() {
		return subjectDAO.getAllSubject();
	}

	public Subject gainSubject(Integer id) {
		return subjectDAO.getSubjectById(id);
	}

	public Subject gainSubject(String name) {
		return subjectDAO.getSubjectByName(name);
	}

	public boolean addNewSubject(Subject subject, Map model) {
		Subject dbSubject = subjectDAO.getSubjectByName(subject.getName());
		if(dbSubject == null){
			Date now = new Date();
			subject.setCst_create(now);
			subject.setCst_modify(now);
			
			subjectDAO.addNewSubject(subject);
			return true;
		}else {
            model.put("error_name", "该科目名称已经存在！");
            return false;
		}
	}

	public boolean editSubjectInfo(Subject subject, Map model) {
		Subject dbSubject = subjectDAO.getSubjectByName(subject.getName());
		if( dbSubject == null || dbSubject.getId().equals(subject.getId())){
			subject.setCst_modify(new Date());
			subjectDAO.updateSubjectInfo(subject);
			return true;
		}else{
			model.put("error_name", "该科目名称已经存在！");
			return false;			
		}
	}

	public List<Chapter> gainChapterList() {
		return chapterDAO.getAllChapter();
	}

	public List<Chapter> gainChapterBySubject(Integer subject_id) {
		return chapterDAO.getChapterBySubject(subject_id);
	}

	public Chapter gainChapter(Integer id) {
		return chapterDAO.getChapterById(id);
	}

	public Chapter gainChapter(String name) {
		return chapterDAO.getChapterByName(name);
	}

	public boolean addNewChapter(Chapter chapter, Map model) {
		Chapter dbChapter = chapterDAO.getChapterByName(chapter.getName());
		if(dbChapter == null){
			Date now = new Date();
			chapter.setCst_create(now);
			chapter.setCst_modify(now);
			
			chapterDAO.addNewChapter(chapter);
			return true;
		}else{
			model.put("error_name", "该章节名称已经存在！");
            return false;
		}
	}

	public boolean editChapterInfo(Chapter chapter, Map model) {
		Chapter dbChapter = chapterDAO.getChapterByName(chapter.getName());
		if(dbChapter == null || dbChapter.getId().equals(chapter.getId())){
			chapter.setCst_modify(new Date());
			chapterDAO.updateChapterInfo(chapter);
			return true;
		}else{
			model.put("error_name", "该章节名称已经存在！");
			return false;			
		}
	}

	public String uploadImage(MultipartHttpServletRequest multipartRequest,
			Map model) {

		String path = null;
		Calendar cal = Calendar.getInstance();
		String root = null;
		String dirName = null;
		File outFileDir = null;
		String imgName = null;
		File outFile = null;
		
		//获取图片
		MultipartFile srcFile = multipartRequest.getFile("picture");
		
		//如果图片不存在，说明用户没有上传，直接返回null
		if (srcFile == null || srcFile.isEmpty()) {
			return null;
        }
		
		//设定图片的保存路径，为：项目文件->WEB-INF->ckImages->当天日期
		root = multipartRequest.getSession().getServletContext().getRealPath("/");
		rootImageDir = "ckImages/";
		dirName = cal.get(Calendar.DAY_OF_MONTH)+"/";
		outFileDir = new File(root+rootImageDir+dirName);
		if (!outFileDir.isDirectory()) {
            outFileDir.mkdirs();
        }
		
		//设定图片的名称为：当前系统毫秒数.jpg
		imgName = System.currentTimeMillis()+".jpg";
		
		//尝试读取图片并放入对应文件夹
		try {
			BufferedImage bufferedImage = ImageIO.read(srcFile.getInputStream());
			if (bufferedImage == null) {
                model.put("error_image", "图片格式不正确！");
                return "error";
            }
			if (bufferedImage.getWidth()>500 || bufferedImage.getHeight()>400 ) {
				model.put("error_image", "图片宽高不得超过500*400.");
                return "error";
			}
			outFile = new File(outFileDir+"/"+imgName);
			ImageIO.write(bufferedImage, "jpeg", outFile);
			//上传成功后，返回图片的文件名（包括上一层文件夹）.
			path = dirName+imgName;
			return path;
		} catch (IOException e) {
			model.put("error_image", "图片上传错误！");
			return "error";
		}
	}

	public String showImage(HttpServletRequest request, String pic) {
		String pic_url = null;
		String root = request.getSession().getServletContext().getRealPath("/");
		pic_url = root+rootImageDir+pic;
		return pic_url;
	}

	private boolean removeImage(HttpServletRequest request, String pic, Map model){
		String root = request.getSession().getServletContext().getRealPath("/");
		String pic_url = root+rootImageDir+pic;
		try {
			File targetImage = new File(pic_url);
			targetImage.delete();
			return true;
		} catch (Exception e) {
			model.put("error_pic", "未知错误！图片删除失败！");
			return false;
		}
	}
	
	public List<Panduan> gainPanduanList() {
		return panduanDAO.getAllPanduan();
	}

	public Panduan gainPanduan(Integer id) {
		return panduanDAO.getPanduanById(id);
	}

	public List<Panduan> gainPanduanByChapter(Integer chapter_id) {
		return panduanDAO.getPanduanByChapter(chapter_id);
	}

	public boolean addNewPanduan(Panduan panduan, Map model) {
		try {
			Date now = new Date();
			panduan.setCst_create(now);
			panduan.setCst_modify(now);
			
			panduanDAO.addNewPanduan(panduan);
			return true;
		} catch (Exception e) {
			model.put("error_panduan", "题目添加失败,请检查内容是否合理");
			return false;
		}
	}

	public boolean editPanduanInfo(MultipartHttpServletRequest multipartRequest, 
			Panduan panduan, Map model) {
		
		//获取数据库中该题的原始信息
		Panduan dbPanduan = panduanDAO.getPanduanById(panduan.getId());
		
		//调用uploadImage方法,根据返回值设置pic的内容.
		String uploadResult = uploadImage(multipartRequest, model);
		
		if(uploadResult==null){
			//说明没有（重新）上传图片. 将图片地址设置为原始地址，即保持不变；
			panduan.setPic(dbPanduan.getPic());
		}else if("error".equals(uploadResult)){
			//说明（重新）上传了图片，但图片的格式或大小有问题.
			return false;
		}else{
			//剩下的情况就是（重新）上传了图片，而且图片已正常上传.
			//将图片的地址设为新的地址，并物理删除原来的图片.
			panduan.setPic(uploadResult);
			removeImage(multipartRequest, dbPanduan.getPic(), model);
		}
		
		//处理题目的其它信息
		panduan.setCst_modify(new Date());
		
		//写入数据库
		panduanDAO.updatePanduanInfo(panduan);
		
		return true;
	}

	public boolean removePanduanImage(HttpServletRequest request, Panduan panduan, Map model) {
		String pic = panduan.getPic();
		
		if(pic==null){
			model.put("error_pic", "此题没有附图！");
			return false;
		}
		
		//物理删除原图片
		boolean isRemoveSuccess = removeImage(request, pic, model);
		
		if(isRemoveSuccess){
			panduan.setCst_modify(new Date());
			panduan.setPic(null);
			panduanDAO.removePanduanImage(panduan);
			return true;
		}else{
			return false;
		}
	}
	
	public List<Panduan> gainPanduanForExercise(Panduan panduan, Map model){
		Integer PANDUAN_NUM = 5;	//指定题目的数量
		
		List<Panduan> panduanListOriginal = panduanDAO.getPanduanForExercise(panduan);
		List<Panduan> panduanList = new ArrayList<Panduan>();
		Integer random = null;
		Integer originalSize = null;
		
		if(panduanListOriginal.isEmpty() == true || panduanListOriginal.size() == 0){
			model.put("error_setting", "没有在题库中找到符合条件的题目，请更改参数后重试.");
			return null;
		}else{
			originalSize = panduanListOriginal.size();
			for(int i=0; i<PANDUAN_NUM; i++){
				random = (int) (originalSize*Math.random());
				panduanList.add(panduanListOriginal.get(random));
			}
		}
		
		return panduanList;
	}

	public List<Xuanze> gainXuanzeList() {
		return xuanzeDAO.getAllXuanze();
	}

	public Xuanze gainXuanze(Integer id) {
		return xuanzeDAO.getXuanzeById(id);
	}

	public List<Xuanze> gainXuanzeByChapter(Integer chapter_id) {
		return xuanzeDAO.getXuanzeByChapter(chapter_id);
	}

	public boolean addNewXuanze(Xuanze xuanze, Map model) {
		try {
			Date now = new Date();
			xuanze.setCst_create(now);
			xuanze.setCst_modify(now);
			
			xuanzeDAO.addNewXuanze(xuanze);
			return true;
		} catch (Exception e) {
			model.put("error_xuanze", "题目添加失败,请检查内容是否合理");
			return false;
		}
	}

	public boolean editXuanzeInfo(MultipartHttpServletRequest multipartRequest,
			Xuanze xuanze, Map model) {

		//获取数据库中该题的原始信息
		Xuanze dbXuanze = xuanzeDAO.getXuanzeById(xuanze.getId());
		
		//调用uploadImage方法,根据返回值设置pic的内容.
		String uploadResult = uploadImage(multipartRequest, model);
		
		if(uploadResult==null){
			//说明没有（重新）上传图片. 将图片地址设置为原始地址，即保持不变；
			xuanze.setPic(dbXuanze.getPic());
		}else if("error".equals(uploadResult)){
			//说明（重新）上传了图片，但图片的格式或大小有问题.
			return false;
		}else{
			//剩下的情况就是（重新）上传了图片，而且图片已正常上传.
			//将图片的地址设为新的地址，并物理删除原来的图片.
			xuanze.setPic(uploadResult);
			removeImage(multipartRequest, dbXuanze.getPic(), model);
		}
		
		//处理题目的其它信息
		xuanze.setCst_modify(new Date());
		
		//写入数据库
		xuanzeDAO.updateXuanzeInfo(xuanze);
		
		return true;
	}

	public boolean removeXuanzeImage(HttpServletRequest request, Xuanze xuanze,
			Map model) {
		String pic = xuanze.getPic();
		
		if(pic==null){
			model.put("error_pic", "此题没有附图！");
			return false;
		}
		
		//物理删除原图片
		boolean isRemoveSuccess = removeImage(request, pic, model);
		
		if(isRemoveSuccess){
			xuanze.setCst_modify(new Date());
			xuanze.setPic(null);
			xuanzeDAO.removeXuanzeImage(xuanze);
			return true;
		}else{
			return false;
		}
	}

	public List<Xuanze> gainXuanzeForExercise(Xuanze xuanze, Map model){
		Integer XUANZE_NUM = 5;	//指定题目的数量
		
		List<Xuanze> xuanzeListOriginal = xuanzeDAO.getXuanzeForExercise(xuanze);
		List<Xuanze> xuanzeList = new ArrayList<Xuanze>();
		String[] orderArray = {"owrc","owcr","orwc","orcw",
							   "ocwr","ocrw","worc","wocr",
							   "wroc","wrco","wcor","wcro",
							   "rowc","rocw","rwoc","rwco",
							   "rcow","rcwo","cowr","corw",
							   "cwor","cwro","crow","crwo"};
		Xuanze xuanze_temp = null;
		Integer random = null;
		Integer originalSize = null;
		
		if(xuanzeListOriginal.isEmpty() == true || xuanzeListOriginal.size() == 0){
			model.put("error_setting", "没有在题库中找到符合条件的题目，请更改参数后重试.");
			return null;
		}else{
			originalSize = xuanzeListOriginal.size();
			for(int i=0; i<XUANZE_NUM; i++){
				//从题目中随机取出一题
				random = (int) (originalSize*Math.random());
				xuanze_temp = xuanzeListOriginal.get(random);
				//打乱选项的顺序
				String order = orderArray[(int)((orderArray.length)*Math.random())];
				
				xuanze_temp.setAnswer_order(order);
				for(int j=0; j<order.length(); j++){
					String temp = null;
					//根据随机数提取出一个选项.
					switch(order.charAt(j)){
					case 'c':
						temp = xuanze_temp.getCorrect_answer();
						break;
					case 'o':
						temp = xuanze_temp.getFalse_one();
						break;
					case 'w':
						temp = xuanze_temp.getFalse_two();
						break;
					case 'r':
						temp = xuanze_temp.getFalse_three();
						break;
					default:
						model.put("error_setting", "服务层的orderArray初始化异常，请联系系统管理员.");
						return null;
					}
					
					//将提取出的选项依次放进ABCD中.
					switch(j){
					case 0:
						xuanze_temp.setAnswer_a(temp);
						break;
					case 1:
						xuanze_temp.setAnswer_b(temp);
						break;
					case 2:
						xuanze_temp.setAnswer_c(temp);
						break;
					case 3:
						xuanze_temp.setAnswer_d(temp);
						break;
					default:
						model.put("error_setting", "服务层的打乱选项时出现异常，请联系系统管理员.");
						return null;
					}
				}
				
				xuanzeList.add(xuanze_temp);
			}
		}
		
		return xuanzeList;
	}
	
	public List<Tiankong> gainTiankongList() {
		return tiankongDAO.getAllTiankong();
	}

	public Tiankong gainTiankong(Integer id) {
		return tiankongDAO.getTiankongById(id);
	}

	public List<Tiankong> gainTiankongByChapter(Integer chapter_id) {
		return tiankongDAO.getTiankongByChapter(chapter_id);
	}

	public boolean addNewTiankong(Tiankong tiankong, Map model) {
		try {
			Date now = new Date();
			tiankong.setCst_create(now);
			tiankong.setCst_modify(now);
			
			tiankongDAO.addNewTiankong(tiankong);
			return true;
		} catch (Exception e) {
			model.put("error_tiankong", "题目添加失败,请检查内容是否合理");
			return false;
		}
	}
	
	public boolean editTiankongInfo(
			MultipartHttpServletRequest multipartRequest, Tiankong tiankong,
			Map model) {

		//获取数据库中该题的原始信息
		Tiankong dbTiankong = tiankongDAO.getTiankongById(tiankong.getId());
		
		//调用uploadImage方法,根据返回值设置pic的内容.
		String uploadResult = uploadImage(multipartRequest, model);
		
		if(uploadResult==null){
			//说明没有（重新）上传图片. 将图片地址设置为原始地址，即保持不变；
			tiankong.setPic(dbTiankong.getPic());
		}else if("error".equals(uploadResult)){
			//说明（重新）上传了图片，但图片的格式或大小有问题.
			return false;
		}else{
			//剩下的情况就是（重新）上传了图片，而且图片已正常上传.
			//将图片的地址设为新的地址，并物理删除原来的图片.
			tiankong.setPic(uploadResult);
			removeImage(multipartRequest, dbTiankong.getPic(), model);
		}
		
		//处理题目的其它信息
		tiankong.setCst_modify(new Date());
		
		//写入数据库
		tiankongDAO.updateTiankongInfo(tiankong);
		
		return true;
	}

	public boolean removeTiankongImage(HttpServletRequest request,
			Tiankong tiankong, Map model) {
		String pic = tiankong.getPic();
		
		if(pic==null){
			model.put("error_pic", "此题没有附图！");
			return false;
		}
		
		//物理删除原图片
		boolean isRemoveSuccess = removeImage(request, pic, model);
		
		if(isRemoveSuccess){
			tiankong.setCst_modify(new Date());
			tiankong.setPic(null);
			tiankongDAO.removeTiankongImage(tiankong);
			return true;
		}else{
			return false;
		}
	}
	
	public List<Tiankong> gainTiankongForExercise(Tiankong tiankong, Map model){
		Integer TIANKONG_NUM = 5;	//指定题目的数量
		
		List<Tiankong> tiankongListOriginal = tiankongDAO.getTiankongForExercise(tiankong);
		List<Tiankong> tiankongList = new ArrayList<Tiankong>();
		Integer random = null;
		Integer originalSize = null;
		
		if(tiankongListOriginal.isEmpty() == true || tiankongListOriginal.size() == 0){
			model.put("error_setting", "没有在题库中找到符合条件的题目，请更改参数后重试.");
			return null;
		}else{
			originalSize = tiankongListOriginal.size();
			for(int i=0; i<TIANKONG_NUM; i++){
				random = (int) (originalSize*Math.random());
				tiankongList.add(tiankongListOriginal.get(random));
			}
		}
		
		return tiankongList;
	}
	
	public List<Zhuguan> gainZhuguanList() {
		return zhuguanDAO.getAllZhuguan();
	}

	public Zhuguan gainZhuguan(Integer id) {
		return zhuguanDAO.getZhuguanById(id);
	}

	public List<Zhuguan> gainZhuguanByChapter(Integer chapter_id) {
		return zhuguanDAO.getZhuguanByChapter(chapter_id);
	}

	public boolean addNewZhuguan(Zhuguan zhuguan, Map model) {
		try {
			Date now = new Date();
			zhuguan.setCst_create(now);
			zhuguan.setCst_modify(now);
			
			zhuguanDAO.addNewZhuguan(zhuguan);
			return true;
		} catch (Exception e) {
			model.put("error_zhuguan", "题目添加失败,请检查内容是否合理");
			return false;
		}
	}

	public boolean editZhuguanInfo(
			MultipartHttpServletRequest multipartRequest, Zhuguan zhuguan,
			Map model) {

		//获取数据库中该题的原始信息
		Zhuguan dbZhuguan = zhuguanDAO.getZhuguanById(zhuguan.getId());
		
		//调用uploadImage方法,根据返回值设置pic的内容.
		String uploadResult = uploadImage(multipartRequest, model);
		
		if(uploadResult==null){
			//说明没有（重新）上传图片. 将图片地址设置为原始地址，即保持不变；
			zhuguan.setPic(dbZhuguan.getPic());
		}else if("error".equals(uploadResult)){
			//说明（重新）上传了图片，但图片的格式或大小有问题.
			return false;
		}else{
			//剩下的情况就是（重新）上传了图片，而且图片已正常上传.
			//将图片的地址设为新的地址，并物理删除原来的图片.
			zhuguan.setPic(uploadResult);
			removeImage(multipartRequest, dbZhuguan.getPic(), model);
		}
		
		//处理题目的其它信息
		zhuguan.setCst_modify(new Date());
		
		//写入数据库
		zhuguanDAO.updateZhuguanInfo(zhuguan);
		
		return true;
	}

	public boolean removeZhuguanImage(HttpServletRequest request,
			Zhuguan zhuguan, Map model) {
		String pic = zhuguan.getPic();
		
		if(pic==null){
			model.put("error_pic", "此题没有附图！");
			return false;
		}
		
		//物理删除原图片
		boolean isRemoveSuccess = removeImage(request, pic, model);
		
		if(isRemoveSuccess){
			zhuguan.setCst_modify(new Date());
			zhuguan.setPic(null);
			zhuguanDAO.removeZhuguanImage(zhuguan);
			return true;
		}else{
			return false;
		}
	}

}
